package org.zy.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import org.zy.core.Message;
import org.zy.core.MessageDecoder;
import org.zy.core.MessageEncoder;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ProxySocket {
    private static EventLoopGroup clientGroup = new NioEventLoopGroup();

    private static final ScheduledExecutorService reconnectExecutor =
            Executors.newSingleThreadScheduledExecutor();

    public static Channel connectProxyServer() {
        reconnectExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                connectProxyServer(null);
            }
        }, 3, 3, TimeUnit.SECONDS);
        return connectProxyServer(null);
    }

    public static Channel connectProxyServer(String visitorId) {
        if (visitorId == null || visitorId.length() == 0) {
            // 建立客户端与代理服务器连接
            if (ClientChannelManager.PROXY_CHANNEL == null || !ClientChannelManager.PROXY_CHANNEL.isActive()) {
                newConnect(null);
            }
            return null;
        } else {
            // 建立访客连接
            Channel channel = ClientChannelManager.VISITOR_CHANNEL_MAP.get(visitorId);
            if (null == channel) {
                newConnect(visitorId);
                channel = ClientChannelManager.VISITOR_CHANNEL_MAP.get(visitorId);
            }
            return channel;
        }

    }

    private static void newConnect(String visitorId) {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(clientGroup).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast(new MessageDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
                        pipeline.addLast(new MessageEncoder());
                        pipeline.addLast(new IdleStateHandler(40, 8, 0));
                        pipeline.addLast(new ProxyHandler());
                    }
                });

        bootstrap.connect(Config.serverIp, Config.serverPort)
                .addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture channelFuture) {
                        if (channelFuture.isSuccess()) {
                            Channel channel = channelFuture.channel();
                            if (visitorId == null || visitorId.length() == 0) {
                                // 客户端与代理服务器连接
                                Message msg = new Message(Message.TYPE_CONNECT, "client".getBytes());
                                channel.writeAndFlush(msg);

                                ClientChannelManager.PROXY_CHANNEL = channel;
                            } else {
                                // 访客连接
                                Message msg = new Message(Message.TYPE_CONNECT, visitorId.getBytes());
                                channel.writeAndFlush(msg);

                                // 客户端Channel绑定与访客关系
                                ClientChannelManager.VISITOR_CHANNEL_MAP.put(visitorId, channel);
                                channel.attr(ClientChannelManager.VISITOR_ID).set(visitorId);

                                Channel realChannel = ClientChannelManager.REAL_CHANNEL_MAP.get(visitorId);
                                if (null != realChannel) {
                                    realChannel.config().setOption(ChannelOption.AUTO_READ, true);
                                }
                            }
                        }
                    }
                });
    }
}
